#include <ani.h>
#include <array>
#include <iostream>
#include <vector>

std::string ANIUtils_ANIStringToStdString(ani_env *env, ani_string ani_str)
{
    ani_size strSize;
    env->String_GetUTF8Size(ani_str, &strSize);

    std::vector<char> buffer(strSize + 1); // +1 for null terminator
    char *utf8_buffer = buffer.data();

    // String_GetUTF8 Supportted by https://gitee.com/openharmony/arkcompiler_runtime_core/pulls/3416
    ani_size bytes_written = 0;
    env->String_GetUTF8(ani_str, utf8_buffer, strSize + 1, &bytes_written);

    utf8_buffer[bytes_written] = '\0';
    std::string content = std::string(utf8_buffer);
    return content;
}

ani_string ANIUtils_StdStringToANIString(ani_env *env, std::string str)
{
    ani_string result_string{};
    env->String_NewUTF8(str.c_str(), str.size(), &result_string);
    return result_string;
}

static ani_string handleData(ani_env *env, [[maybe_unused]] ani_object obj, ani_string ani_str)
{
    std::cout<<"old message:"<< ANIUtils_ANIStringToStdString(env, ani_str) << std::endl;;
    std::string msg = "this message in cpp";
    auto newANIString = ANIUtils_StdStringToANIString(env, msg);
    return newANIString;
}


ani_status ANI_Constructor(ani_vm *vm, uint32_t *result)
{
    ani_env *env;

    if (ANI_OK != vm->GetEnv(ANI_VERSION_1, &env))
    {
        std::cerr << "Unsupported ANI_VERSION_1" << std::endl;
        return ANI_ERROR;
    }

    static const char *className = "ani_string.ETSGLOBAL";

    ani_class cls;
    if (ANI_OK != env->FindClass(className, &cls))
    {
        std::cerr << "Not found '" << className << "'" << std::endl;
        return ANI_ERROR;
    }

    std::array methods = {
        ani_native_function{"handleData", "C{std.core.String}:C{std.core.String}", reinterpret_cast<void *>(handleData)},
    };

    std::cout << "Start bind native methods to '" << className << "'" << std::endl;

    if (ANI_OK != env->Class_BindNativeMethods(cls, methods.data(), methods.size()))
    {
        std::cerr << "Cannot bind native methods to '" << className << "'" << std::endl;
        return ANI_ERROR;
    };
    std::cout << "Finish bind native methods to '" << className << "'" << std::endl;

    *result = ANI_VERSION_1;
    return ANI_OK;
}